package com.es.repository.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.es.constant.EsPageConstant;
import com.es.dto.*;
import com.es.enums.EsMetricEnum;
import com.es.repository.EsApi;
import com.es.util.EsUtil;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.action.DocWriteResponse;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.*;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.GeoDistanceQueryBuilder;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.reindex.DeleteByQueryRequest;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.aggregations.Aggregation;
import org.elasticsearch.search.aggregations.AggregationBuilders;
import org.elasticsearch.search.aggregations.Aggregations;
import org.elasticsearch.search.aggregations.BucketOrder;
import org.elasticsearch.search.aggregations.bucket.terms.Terms;
import org.elasticsearch.search.aggregations.bucket.terms.TermsAggregationBuilder;
import org.elasticsearch.search.aggregations.metrics.*;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.FetchSourceContext;
import org.elasticsearch.search.sort.FieldSortBuilder;
import org.elasticsearch.search.sort.GeoDistanceSortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.suggest.Suggest;
import org.elasticsearch.search.suggest.SuggestBuilder;
import org.elasticsearch.search.suggest.completion.CompletionSuggestion;
import org.elasticsearch.search.suggest.completion.CompletionSuggestionBuilder;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.IOException;
import java.util.*;

/**
 * @author 文雪峰
 * @date 2019/12/19 19:37
 * @description 简单描述
 **/
@Slf4j
@Service
public class EsApiImpl<T> implements EsApi<T> {
    @Resource
    RestHighLevelClient client;

    /**
     * 保存
     *
     * @param t     保存对象
     * @param index 索引名称
     * @param id    id
     * @return 返回 true 成功 反则失败
     */
    @Override
    public boolean save(T t, String index, String id) {
        // 操作索引的request
        IndexRequest indexRequest = new IndexRequest(index);
        String json = JSON.toJSONString(t);
        // 设置文档id
        indexRequest.id(id);
        // es 以JSON 交互
        indexRequest.source(json, XContentType.JSON);
        try {
            // RequestOptions.DEFAULT 默认的请求的选项
            IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
            // IndexResponse.getResult 获取返回结果
            if (indexResponse.getResult() == DocWriteResponse.Result.CREATED) {
                log.info("保存成功");
            } else if (indexResponse.getResult() == DocWriteResponse.Result.UPDATED) {
                log.info("存在id{}" + id + "该数据已更新");
            } else {
                return false;
            }
        } catch (Exception e) {
            log.error("保存失败", e);
        }
        return true;
    }

    /**
     * 批量保存
     *
     * @param list   批量保存对象集合
     * @param index  索引名称
     * @param idList id集合
     * @return 返回 true 成功 反则失败
     */
    @Override
    public boolean batchSave(List<T> list, String index, List<String> idList) {
        if (!EsUtil.judgeList(list)) {
            log.error("批量保存对象集合为空");
            return false;
        }
        // 批量操作的请求类
        // 它并不知道 你要新增/修改/删除/查询
        BulkRequest request = new BulkRequest();
        for (int i = 0; i < list.size(); i++) {
            request.add(new IndexRequest(index).id(idList.get(i)).source(JSON.toJSONString(list.get(i)), XContentType.JSON));
        }
        try {
            // 批量返回类
            BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
            // Bulk响应提供了一种方法来快速检查一个或多个操作是否失败  hasFailures
            // 有一个操作失败，此方法将返回true
            if (responses.hasFailures()) {
                log.info("批量保存失败");
                return false;
            }
            log.info("批量保存成功");
        } catch (Exception e) {
            log.error("批量新增出现异常", e);
        }
        return true;
    }

    /**
     * 查询
     *
     * @param queryBuilder 查询条件
     * @param pagePramDto  分页查询参数
     * @return 返回对应集合
     */
    @Override
    public EsPageDTO<T> pageSearch(QueryBuilder queryBuilder, EsPageParamDTO<T> pagePramDto) {
        List<T> list = new LinkedList<>();
        // 查询请求
        SearchRequest searchRequest = new SearchRequest(pagePramDto.getIndex());
        // 查询条件类
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        Integer pageNo = pagePramDto.getPageNo();
        Integer pageSize = pagePramDto.getPageSize();
        int zero = 0;
        int one = 1;
        searchSourceBuilder.from(((pageNo <= zero ? zero : pageNo - one) * pageSize));
        // 一次性最大10000条
        // 默认情况下ES只能支持最多10000条的展示,这个问题涉及到它的底层和深度分页响应的问题
        searchSourceBuilder.size(pageSize);
        searchRequest.source(searchSourceBuilder);
        // 排序
        if (EsUtil.judgeList(pagePramDto.getSortBuilderList())) {
            List<FieldSortBuilder> sortBuilderList = pagePramDto.getSortBuilderList();
            sortBuilderList.forEach(searchSourceBuilder::sort);
        }
        return page(pageNo, pageSize, searchRequest, list, pagePramDto.getClazz());
    }

    /**
     * 条件查询
     *
     * @author: wxf
     * @date: 2020/7/23 10:07
     * @param queryBuilder 查询条件
     * @param esSearchParamDto 查询参数
     * @return: {@link List<T>}
     **/
    @Override
    public List<T> search(QueryBuilder queryBuilder, EsSearchParamDTO<T> esSearchParamDto) {
        List<T> list = new LinkedList<>();
        // 查询请求
        SearchRequest searchRequest = new SearchRequest(esSearchParamDto.getIndex());
        // 查询条件类
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        // 一次性最大10000条
        // 默认情况下ES只能支持最多10000条的展示,这个问题涉及到它的底层和深度分页响应的问题
        searchSourceBuilder.from(EsPageConstant.MIN_PAGE_NO);
        searchSourceBuilder.size(EsPageConstant.MAX_PAGE_SIZE);
        searchRequest.source(searchSourceBuilder);
        // 排序
        if (EsUtil.judgeList(esSearchParamDto.getSortBuilderList())) {
            List<FieldSortBuilder> sortBuilderList = esSearchParamDto.getSortBuilderList();
            sortBuilderList.forEach(searchSourceBuilder::sort);
        }
        try {
            esJsonResultToObj(list, searchRequest, esSearchParamDto.getClazz());
        } catch (Exception e) {
            log.error("查询出现异常", e);
            e.printStackTrace();
        }
        return list;
    }

    /**
     * es返回的JSON格式结果 转换为业务对应的obj对象
     *
     * @author: wxf
     * @date: 2020/7/23 10:24
     * @param list 返回集合
     * @param searchRequest es查询请求类
     * @param clazz 类泛型
     **/
    private void esJsonResultToObj(List<T> list, SearchRequest searchRequest, Class<T> clazz) {
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            // 搜索命中
            SearchHits hits = searchResponse.getHits();
            // 获取命中的数组
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit hit : searchHits) {
                // JSON转换返回
                T t = JSON.parseObject(hit.getSourceAsString(), clazz);
                list.add(t);
            }
        } catch (IOException e) {
            log.error("查询出现异常", e);
        }
    }

    /**
     * 获取根据id
     *
     * @param id    id
     * @param index 索引名称
     * @param clazz 转换对象
     * @return 返回对应对象
     */
    @Override
    public T getById(String id, String index, Class<T> clazz) {
        GetRequest request = new GetRequest(index, id);
        T t = null;
        try {
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            if (response.isExists()) {
                t = JSON.parseObject(response.getSourceAsString(), clazz);
            }
        } catch (Exception e) {
            log.error("查询id" + id + "出现异常", e);
        }
        return t;
    }

    @Override
    public T getById(String id, String index, Class<T> clazz, String[] excludes) {
        GetRequest request = new GetRequest(index, id);
        FetchSourceContext sourceContext = new FetchSourceContext(true, null, excludes);
        request.fetchSourceContext(sourceContext);
        T t = null;
        try {
            GetResponse response = client.get(request, RequestOptions.DEFAULT);
            if (response.isExists()) {
                t = JSON.parseObject(response.getSourceAsString(), clazz);
            }
        } catch (Exception e) {
            log.error("查询id" + id + "出现异常", e);
        }
        return t;
    }

    /**
     * 获取集合根据id集合
     *
     * @param idList id集合
     * @param index  索引名称
     * @param clazz  转换对象
     * @return 返回对应对象集合
     */
    @Override
    public List<T> getListByIdList(List<String> idList, String index, Class<T> clazz) {
        MultiGetRequest request = new MultiGetRequest();
        idList.forEach(
                i -> request.add(new MultiGetRequest.Item(index, i))
        );
        List<T> list = new ArrayList<>(idList.size());
        try {
            MultiGetResponse mget = client.mget(request, RequestOptions.DEFAULT);
            // 批量查询 返回的对应的每个查询对应的数据
            MultiGetItemResponse[] response = mget.getResponses();
            for (MultiGetItemResponse multiGetItemResponse : response) {
                GetResponse getResponse = multiGetItemResponse.getResponse();
                if (getResponse.isExists()) {
                    list.add(JSON.parseObject(getResponse.getSourceAsString(), clazz));
                }
            }
        } catch (Exception e) {
            log.error("id批量查询出现异常" + idList, e);
        }
        return list;
    }

    /**
     * 修改
     *
     * @param t     修改对象
     * @param index 索引名称
     * @param id    id
     * @return 返回 true 成功 反则失败
     */
    @Override
    public boolean update(T t, String index, String id) {
        UpdateRequest request = new UpdateRequest(index, id);
        // SerializerFeature.WriteMapNullValue null的值 也转换成JSON格式
        // ES是根据JSON字段更新 JSON里面有那些字段 ES就更新那些字段 字段值是null也会更新会null
        String jsonString = JSON.toJSONString(t, SerializerFeature.WriteMapNullValue);
        request.doc(jsonString, XContentType.JSON);
        boolean flag = false;
        try {
            UpdateResponse update = client.update(request, RequestOptions.DEFAULT);
            if (update.getResult() == DocWriteResponse.Result.CREATED) {
                log.info("ES中没有数据新增成功");
                flag = true;
            } else if (update.getResult() == DocWriteResponse.Result.UPDATED) {
                log.info("修改成功");
                flag = true;
            } else if (update.getResult() == DocWriteResponse.Result.NOOP) {
                log.info("修改成功");
                flag = true;
            } else {
                log.info("修改失败,ES返回修改状态" + update.getResult());
            }
        } catch (Exception e) {
            log.error("修改出现异常", e);
        }
        return flag;
    }

    /**
     * 批量修改
     *
     * @param t      修改对象集合
     * @param index  索引名称
     * @param idList id集合
     * @return 返回 true 成功 反则失败
     */
    @Override
    public boolean batchUpdate(List<T> t, String index, List<String> idList) {
        if (!EsUtil.judgeList(t)) {
            return false;
        }
        BulkRequest request = new BulkRequest();
        int size = t.size();
        for (int i = 0; i < size; i++) {
            request.add(new UpdateRequest(index, idList.get(i)).doc(JSON.toJSONString(t.get(i), SerializerFeature.WriteMapNullValue), XContentType.JSON));
        }
        try {
            BulkResponse response = client.bulk(request, RequestOptions.DEFAULT);
            if (response.hasFailures()) {
                return false;
            }
        } catch (Exception e) {
            log.error("批量修改出现异常", e);
        }
        return true;
    }

    /**
     * 方法描述
     *
     * @param id    es文档id
     * @param index 索引名称
     * @author: wxf
     * @date: 2020/7/23 10:36id
     * @return: {@link boolean}
     **/
    @Override
    public boolean deleteById(String id, String index) {
        DeleteRequest request = new DeleteRequest(index, id);
        boolean flag = false;
        try {
            DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
            if (DocWriteResponse.Result.DELETED == delete.getResult()) {
                flag = true;
                log.info("删除id{}" + id + "索引数据成功");
            }
        } catch (IOException e) {
            log.error("id{}" + id + "删除异常", e);
        }
        return flag;
    }

    /**
     * 批量删除
     *
     * @param queryBuilder 查询条件
     * @param index        索引名称
     * @author: wxf
     * @date: 2020/7/23 10:49
     * @return: {@link boolean}
     **/
    @Override
    public void batchDelete(BoolQueryBuilder queryBuilder, String index) {
        DeleteByQueryRequest request = new DeleteByQueryRequest(index);
        request.setQuery(queryBuilder);
        try {
            client.deleteByQuery(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            log.error("批量删除异常", e);
        }
    }

    /**
     * 经纬度查询
     *
     * @author: wxf
     * @date: 2020/7/22 18:10
     * @param queryBuilder 查询条件
     * @param esLocationParamDto  经纬度查询条件
     * @return: {@link EsPageDTO<T>}
     **/
    @Override
    public EsPageDTO<T> locationSearch(BoolQueryBuilder queryBuilder, EsLocationParamDTO<T> esLocationParamDto) {
        int pageNo = esLocationParamDto.getPageNo();
        int pageSize = esLocationParamDto.getPageSize();
        // 维度
        double lat = esLocationParamDto.getLat();
        // 经度
        double lon = esLocationParamDto.getLon();
        // 当前维度,经度
        String location  = esLocationParamDto.getLocation();
        String index = esLocationParamDto.getIndex();
        // 经纬度筛选
        if (null != esLocationParamDto.getDistance()) {
            GeoDistanceQueryBuilder geoQueryBuilder = QueryBuilders.geoDistanceQuery(location)
                    // 维度，经度
                    .point(lat, lon)
                    // 范围
                    .distance(esLocationParamDto.getDistance(), esLocationParamDto.getDistanceUnit())
                    .geoDistance(GeoDistance.ARC);
            // 同时满足 范围查找 和 QueryBuilder里面的查询条件
            queryBuilder.must(geoQueryBuilder);
        }
        // 按距离排序
        GeoDistanceSortBuilder sort = SortBuilders.geoDistanceSort(location, lat, lon)
                .unit(esLocationParamDto.getDistanceUnit());
        if (!Objects.isNull(esLocationParamDto.getSortOrder())) {
            // 排序
            sort.order(esLocationParamDto.getSortOrder());
        }
        SearchSourceBuilder searchSourceBuilder = SearchSourceBuilder.searchSource()
                .from((pageNo - 1) * pageSize)
                .size(pageSize)
                .query(queryBuilder);
        // 条件排序
        if (null != esLocationParamDto.getSortBuilderList()) {
            List<FieldSortBuilder> sortBuilderList = esLocationParamDto.getSortBuilderList();
            sortBuilderList.forEach(searchSourceBuilder::sort);
        }
        searchSourceBuilder.sort(sort);
        if (null != esLocationParamDto.getExcludes() && 0 < esLocationParamDto.getExcludes().length) {
            FetchSourceContext sourceContext = new FetchSourceContext(true, null, esLocationParamDto.getExcludes());
            searchSourceBuilder.fetchSource(sourceContext);
        }
        // 查询请求
        SearchRequest searchRequest = new SearchRequest(index);
        searchRequest.source(searchSourceBuilder);
        List<T> list = new LinkedList<>();
        return page(pageNo, pageSize, searchRequest, list, esLocationParamDto.getClazz());
    }

    /**
     * 聚合指标查询 求和、最小、最大、统计、平均
     * @auther: wxf
     * @date: 2020/10/18 13:46
     * @param queryBuilder 查询条件
     * @param esMetricParamDTO 指标查询参数
     * @return: {@link Double} 指标返回的是一个 double 值
     * es 指标返回格式
     * maxAge 对应 customName 的 自定义逻辑名称
     * "aggregations" : {
     *     "maxAge" : {
     *       "value" : 22.0
     *     }
     *   }
     */
    @Override
    public Double metricSearch(BoolQueryBuilder queryBuilder, EsMetricParamDTO esMetricParamDTO) {
        EsMetricEnum esMetricEnum = esMetricParamDTO.getEsMetricEnum();
        String customName = esMetricParamDTO.getCustomName();
        String field = esMetricParamDTO.getField();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        if (EsMetricEnum.count == esMetricEnum) {
            searchSourceBuilder.aggregation(AggregationBuilders.count(customName).field(field));
        } else if (EsMetricEnum.min == esMetricEnum) {
            searchSourceBuilder.aggregation(AggregationBuilders.min(customName).field(field));
        } else if (EsMetricEnum.max == esMetricEnum) {
            searchSourceBuilder.aggregation(AggregationBuilders.max(customName).field(field));
        } else if (EsMetricEnum.sum == esMetricEnum) {
            searchSourceBuilder.aggregation(AggregationBuilders.sum(customName).field(field));
        } else if (EsMetricEnum.avg == esMetricEnum) {
            searchSourceBuilder.aggregation(AggregationBuilders.avg(customName).field(field));
        }
        if (!Objects.isNull(queryBuilder)) {
            searchSourceBuilder.query(queryBuilder);
        }
        // 设置返回符合条件的数据 0-返回0条 1-返回1条
        searchSourceBuilder.size(0);
        SearchRequest searchRequest = new SearchRequest(esMetricParamDTO.getIndex());
        searchRequest.source(searchSourceBuilder);;
        Double metricValue = null;
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            if (EsMetricEnum.count == esMetricEnum) {
                ValueCount count = searchResponse.getAggregations().get(customName);
                long value = count.getValue();
                metricValue = Double.parseDouble(String.valueOf(value));
            } else if (EsMetricEnum.min == esMetricEnum) {
                ParsedMin min = searchResponse.getAggregations().get(customName);
                metricValue = min.getValue();
            } else if (EsMetricEnum.max == esMetricEnum) {
                ParsedMax max = searchResponse.getAggregations().get(customName);
                metricValue = max.getValue();
            } else if (EsMetricEnum.sum == esMetricEnum) {
                ParsedSum sum = searchResponse.getAggregations().get(customName);
                metricValue = sum.getValue();
            } else if (EsMetricEnum.avg == esMetricEnum) {
                ParsedAvg avg = searchResponse.getAggregations().get(customName);
                metricValue = avg.getValue();
            }
        } catch (IOException e) {
            log.error("指标查询异常", e);
        }
        return metricValue;
    }

    /**
     * 聚合查询 对应 mysql 的 分组查询
     *
     * @param queryBuilder   查询条件
     * @param esAggsParamDTO 聚合查询参数
     * @auther: wxf
     * @date: 2020/10/18 14:47
     * @return: {@link Map< String, String>}
     */
    @Override
    public Map<String, String> aggsSearch(BoolQueryBuilder queryBuilder, EsAggsParamDTO esAggsParamDTO) {
        String customName = esAggsParamDTO.getCustomName();
        String field = esAggsParamDTO.getField();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        TermsAggregationBuilder aggregation = AggregationBuilders.terms(customName)
                .field(field);
        if (!Objects.isNull(queryBuilder)) {
            searchSourceBuilder.query(queryBuilder);
        }
        // 设置返回符合条件的数据 0-返回0条 1-返回1条
        searchSourceBuilder.size(0);
        searchSourceBuilder.aggregation(aggregation);
        SearchRequest searchRequest = new SearchRequest(esAggsParamDTO.getIndex());
        searchRequest.source(searchSourceBuilder);
        Map<String, String> aggsMap = new HashMap<>(16);
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            Aggregations aggregations = searchResponse.getAggregations();
            Terms terms = aggregations.get(customName);
            if (!Objects.isNull(terms)) {
                if (EsUtil.judgeList(terms.getBuckets())) {
                    terms.getBuckets().forEach(
                            i -> {
                                String key = i.getKeyAsString();
                                long count = i.getDocCount();
                                aggsMap.put(key, String.valueOf(count));
                            }
                    );
                }
            }
        } catch (IOException e) {
            log.error("聚合查询异常", e);
        }
        return aggsMap;
    }

    private EsPageDTO<T> page(int pageNo, int pageSize, SearchRequest searchRequest, List<T> list, Class<T> clazz) {
        EsPageDTO<T> esPageDto = new EsPageDTO<>();
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            // 搜索命中
            SearchHits hits = searchResponse.getHits();
            // 获取命中的数组
            SearchHit[] searchHits = hits.getHits();
            for (SearchHit hit : searchHits) {
                // JSON转换返回
                T t = JSON.parseObject(hit.getSourceAsString(), clazz);
                list.add(t);
            }
            esPageDto.setList(list);
            esPageDto.setPageNo(pageNo);
            esPageDto.setPageSize(pageSize);
            long total = hits.getTotalHits().value;
            esPageDto.setTotal(total);
            int totalPage = (int) total / pageSize;
            if (total % pageSize != 0) {
                totalPage++;
            }
            esPageDto.setTotalPage(totalPage);
        } catch (Exception e) {
            log.error("查询出现异常", e);
        }
        return esPageDto;
    }

    /**
     * 高效前缀匹配搜索
     *
     * @author: wxf
     * @date: 2020/8/20 9:16
     * @param paramDTO 匹配参数
     * @return: {@link List< String>}
     **/
    @Override
    public List<String> completionSuggestSearch(EsCompletionSuggestParamDTO paramDTO) {
        String fieldName = paramDTO.getFieldName();
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        SuggestBuilder suggestBuilder = new SuggestBuilder();
        CompletionSuggestionBuilder completionSuggestionBuilder =
                new CompletionSuggestionBuilder(fieldName + ".suggest");
        completionSuggestionBuilder.text(paramDTO.getFieldValue());
        completionSuggestionBuilder.size(EsPageConstant.PAGE_SIZE);
        suggestBuilder.addSuggestion("suggest_" + fieldName, completionSuggestionBuilder);
        searchSourceBuilder.suggest(suggestBuilder);
        SearchRequest searchRequest = new SearchRequest(paramDTO.getIndexArray());
        searchRequest.source(searchSourceBuilder);
        List<String> list = new ArrayList<>(EsPageConstant.PAGE_SIZE);
        try {
            SearchResponse searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
            Suggest suggest = searchResponse.getSuggest();
            if (suggest == null) {
                return null;
            }
            CompletionSuggestion completionSuggestion = suggest.getSuggestion("suggest_" + fieldName);
            for (CompletionSuggestion.Entry entry : completionSuggestion.getEntries()) {
                for (CompletionSuggestion.Entry.Option option : entry) {
                    String suggestText = option.getText().string();
                    list.add(suggestText);
                }
            }
        } catch (IOException e) {
            log.error("");
        }
        return list;
    }
}
